package com.study.io.nio.demo.buffer;

import com.study.common.utils.RamUtil;

import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * MappedByteBuffer demo
 * 内存映射 减少一次内存拷贝 直接从磁盘拷贝到物理内存 内核空间与用户空间同时映射
 * <p>
 * 以下是jdk1.8手册内容
 * 直接字节缓冲区，其内容是文件的内存映射区域。
 * 映射的字节缓冲区通过FileChannel.map方法创建。此类使用特定于内存映射文件区域的操作扩展ByteBuffer类。
 * 映射的字节缓冲区及其表示的文件映射在缓冲区本身被垃圾收集之前保持有效。
 * 映射字节缓冲区的内容可以随时改变，例如，如果该程序或其他程序改变了映射文件的相应区域的内容。这些变化是否发生以及何时发生，都取决于操作系统，因此未指定。
 * 映射字节缓冲区的全部或部分可能随时变得不可访问，例如，如果映射文件被截断。尝试访问映射字节缓冲区的不可访问区域不会更改缓冲区的内容，并且会在访问时或稍后的某个时间引发未指定的异常。
 * 因此，强烈建议采取适当的预防措施，以避免此程序或同时运行的程序操纵映射文件，但读取或写入文件的内容除外。
 * 映射字节缓冲区的行为与普通的直接字节缓冲区没有区别。
 *
 * @author Lenovo
 */
public class MappedByteBufferDemo {

    public static void main(String[] args) {
        try {
            RandomAccessFile file = new RandomAccessFile("d://file.txt", "rw");
            FileChannel fc = file.getChannel();
            MappedByteBuffer mappedByteBuffer = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size());
            mappedByteBuffer.load();

            //打印内存日志
            RamUtil.getRam();
            //标记
            //mappedByteBuffer.mark();
            //写入数据
            //mappedByteBuffer.put("[2019-0".getBytes());
            //修改posi地址
            //mappedByteBuffer.reset();
            //读取数据
            byte[] b = new byte[1024 * 1];
            mappedByteBuffer.get(b);
            //打印内存日志
            RamUtil.getRam();

            String s = new String(b);
            System.out.println(new String(b));

            //打印内存日志
            RamUtil.getRam();

            //mappedByteBuffer.clear();

            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
